﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Web;
using RssToolkit.Rss;
using HttpClient = System.Net.Http.HttpClient;

namespace BlogsAPI.Sites
{
    using System;
    using System.Text;
    using System.IO;
    using System.Net;
    using System.Text.RegularExpressions;
    using Abstract;
    using Interfaces;

    /// <summary>
    /// http://blogs.mail.ru/
    /// </summary>
    /// <remarks>
    /// Очень важная особенность в том, что все имена пользователей обрабатываются как "username" и UserID=list
    /// так как различаются пользователи с почтами в разных доменах =(
    /// </remarks>
    [Obsolete("Mail.ru закрыли свои блоги")]
    [BlogServiceAPI(Description = "http://blogs.mail.ru/", Link = "http://blogs.mail.ru/")]
    public class BlogsMail : BlogServer, IPosts, IComments, ILike, IVideoHost
    {
        private static readonly Regex Validation = new Regex(@"^http://(?:www\.)?(?:blogs|my)\.mail\.ru(?:/video)?/(?:mail|bk|list|inbox|community)/", Regexoptions);
        private static readonly Regex ValidationFull = new Regex(@"^http://(?:www\.)?(?:blogs|my)\.mail\.ru(?:/video)?/(mail|bk|list|inbox|community)/(.*?)(?:/|$)", Regexoptions);
        
        private static readonly Regex rReaders = new Regex(
            @"<tr>\s*<td class\W+gr bold\W+Читателей:</td>\s*<td class\W+gr\D+(\d+)</td>\s*</tr>",
            Regexoptions);

        private static readonly Regex rComments = new Regex(
            @"comment_(\w+)$", 
            Regexoptions);

        [DebuggerStepThrough]
        public BlogsMail()
        {
            Encoding = Encoding.GetEncoding(1251);//windows-1251
        }

        #region interface: BlogServer

        /// <summary>
        /// Нету больше таких блогов
        /// </summary>
        public override bool HasRating
        {
            get { return false; }
        }

        /// <summary>
        /// проверка, является ли передаваемый урл чатью этого сервиса
        /// </summary>
        public override Boolean ValidateLink(String sLink)
        {
            return Validation.Match(sLink).Success;
        }

        /// <summary>
        /// проверка, является ли передаваемый урл чатью этого сервиса
        /// </summary>
        /// <param name="sLink">ссылка для проверки</param>
        /// <param name="userName">Имя пользователя на блогохостинге</param>
        /// <param name="bType">Тип блога - сообщество или блог</param>
        public override Boolean ValidateLink(String sLink, out String userName, out BlogType bType)
        {
            bType = BlogType.Unknown;
            var m = ValidationFull.Match(sLink);
            if (m.Success)
            {
                //сообщество или одиночный блог
                bType = String.Compare("community", m.Groups[1].ToString()) == 0 ?
                    BlogType.Community : BlogType.User;
                userName = m.Groups[2].ToString();
                if (bType == BlogType.User)
                {
                    _userId = m.Groups[1].ToString();
                }
            }else{
                userName = String.Empty;
            }
            return m.Success;
        }

        /// <summary>
        /// Получение ссылки на блог блогера
        /// </summary>
        /// <param name="userName">ник блогера</param>
        /// <param name="btype">Тип блога - сообщество или блог</param>
        public override String GetBlogLink(string userName, BlogType btype)
        {
            return btype == BlogType.Community
                       ? String.Format("http://my.mail.ru/community/{0}", userName)
                       : String.Format("http://blogs.mail.ru/{0}/{1}",
                                       String.IsNullOrEmpty(_userId) ? "mail" : _userId,
                                       userName);
        }

        /// <summary>
        /// Получение ссылки на блог блогера
        /// </summary>
        /// <param name="userName">ник блогера</param>
        /// <param name="btype">Тип блога - сообщество или блог</param>
        /// <remarks>Неработает если имя пользователя русское, тогда нужен номер</remarks>
        public override String GetRssLink(string userName , BlogType btype)
        {
            return btype == BlogType.Community
                       ? String.Format("http://my.mail.ru/community/{0}/journal/?rss=1", userName)
                       : String.Format("http://blogs.mail.ru/{0}/{1}/?rss=1",
                          String.IsNullOrEmpty(_userId) ? "mail" : _userId,
                          userName);
        }

        /// <summary>
        /// Определение числа читателей блога
        /// </summary>
        /// <param name="username">имя</param>
        /// <param name="bt">тип</param>
        /// <returns></returns>
        public override uint? HowManyReaders(string username, BlogType bt)
        {
            try
            {
                if(bt == BlogType.Community)
                {
                    //чтобы просматривать данные по сообществам нужно быть залогиненным =(
                    return null;
                }
                String blogname = GetBlogLink(username, bt);
                HttpWebRequest myHttpWebRequest = MakeRequest(blogname + "/info");
                myHttpWebRequest.Method = "GET"; // метод GET
                myHttpWebRequest.Referer = blogname;
                //получаем ответ и его разбираем...
                HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                string result = new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding).ReadToEnd();
                myHttpWebResponse.Close();
                //ПОЛУЧИЛИ xml - откроемка его...
                Match m = rReaders.Match(result);
                if (m.Success)
                {
                    return uint.Parse(m.Groups[1].Value);
                }
            }
            catch (Exception e1)
            {
                Debug.WriteLine("Ошибка загрузки числа читателей: " + e1.Message);
            }
            return null;
        }

        #endregion
        
        #region interface: IPosts/IComments

        /// <summary>
        /// REMOVED BY MAIL.RU
        /// Получение списка последнних записей
        /// </summary>
        /// <param name="options">поисковые параметры</param>
        /// <returns></returns>
        //public List<BlogPost> GetLatest(string options = "age=a&sex=a&type=1")
        //{
        //    var oRet = new List<BlogPost>();
        //    try
        //    {
        //        string mainpage = String.Format("http://blogs.mail.ru/cgi-bin/journal/last_public_posts?rss=1&{0}", options);
        //        RssDocument xDoc = RssDocument.Load(new Uri(mainpage),false);
        //        if(xDoc!=null)
        //        {
        //            oRet.AddRange(from RssItem rssItem in xDoc.Channel.Items select new BlogPost(new Uri(rssItem.Link))
        //                {
        //                    Body = rssItem.Description, Subject = rssItem.Title, Published = rssItem.PubDateParsed, Links = 0,Comments = 0
        //                });
        //        }
        //    }
        //    catch (Exception e1)
        //    {
        //        Debug.Write(e1);
        //    }
        //    return oRet;
        //}

        /// <summary>
        /// Выкладывание записи в блоге
        /// </summary>
        /// <param name="user">Аккаунт блогера</param>
        /// <param name="bp">пост для блога</param>
        /// <returns></returns>
        public override PostResult MakePost(UserAccount user, BlogPost bp)
        {
            PostResult ps = new PostResult {Error = new NotImplementedException()};
            try
            {
                //при залогинивании заодно определиться номер пользователя
                if (!LogInto(user))
                {
                    throw new Exception("BlogsMail: не удалось залогинится");
                }
                //access_select 
                HttpWebRequest myHttpWebRequest = MakeRequest("http://blogs.mail.ru/cgi-bin/journal/jupdate");
                //вначале нужен гет, чтобы получить секретные числа(!)

                myHttpWebRequest.AllowAutoRedirect = false;
                var myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                //получаем ответ

                string reply = (new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding)).ReadToEnd();

                Match m = new Regex(@"<input[^>]+?name\W+mna[^>]+?value\W+(\d+)[^>]+>").Match(reply);
                if(!m.Success) throw new Exception("Cant find MNA secret number");
                string mna = m.Groups[1].Value;
                m = new Regex(@"<input[^>]+?name\W+mnb[^>]+?value[^\w-]+([-\d]+)[^>]+>").Match(reply);
                if (!m.Success) throw new Exception("Cant find MNB secret number");
                string mnb = m.Groups[1].Value;
                //DefaultJournal
                if (String.IsNullOrEmpty(bp.SpecialParam))//не задан никакой специальных журнал
                {
                    m = new Regex(@"<input[^>]+?name\W+DefaultJournal[^>]+?value\W+(\d+)[^>]+>").Match(reply);
                    if (!m.Success) throw new Exception("Cant find DefaultJournal secret number");
                    bp.SpecialParam = m.Groups[1].Value;
                }

                myHttpWebResponse.Close();
                //а теперь постим!
                myHttpWebRequest = MakeRequest("http://blogs.mail.ru/cgi-bin/journal/jupdate");

                myHttpWebRequest.Method = "POST";
                //выставили куку
                myHttpWebRequest.Referer = GetBlogLink(user.username);
                //////////////////////////
                //multipart/form-data!!!!
                string boundary = Guid.NewGuid().ToString();
                myHttpWebRequest.ContentType = string.Format("multipart/form-data;boundary={0}", boundary);
                // Build Contents for Post
                string header = string.Format("--{0}", boundary);
                string footer = header + "--";
                var contents = new StringBuilder();
                //параметр защиты
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"mna\"");
                contents.AppendLine();
                contents.AppendLine(mna);
                //параметр защиты
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"mnb\"");//NOTE: here is a problem =(
                contents.AppendLine();
                contents.AppendLine(mnb);
                //само содержимое запроса
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"post\"");
                contents.AppendLine();
                contents.AppendLine();
                //второй параметр пошел
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"postid\"");
                contents.AppendLine();
                contents.AppendLine();
                // 
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"back\"");
                contents.AppendLine();
                contents.AppendLine();
                //
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"hidden_by_admin\"");
                contents.AppendLine();
                contents.AppendLine();
                // 
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"text\"");
                contents.AppendLine();
                contents.AppendLine();
                //
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"back\"");
                contents.AppendLine();
                contents.AppendLine();
                //
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"plainmode\"");
                contents.AppendLine();
                contents.AppendLine("0");
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"HTMLMessage\"");
                contents.AppendLine();
                contents.AppendLine("1");
//
                                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"ProKey\"");
                contents.AppendLine();
                contents.AppendLine("1");
                //
                                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"user\"");
                contents.AppendLine();
                contents.AppendLine(user.username + "@" + 
                    (String.IsNullOrEmpty(_userId) ? "mail" : _userId) +".ru");
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Subject\"");
                contents.AppendLine();
                contents.AppendLine(bp.Subject);
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Body\"");
                contents.AppendLine();
                contents.AppendLine(bp.Body);
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Tags\"");
                contents.AppendLine();
                contents.AppendLine(bp.GetParam(PostParams.Tags).ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"MoodText\"");
                contents.AppendLine();
                contents.AppendLine(bp.GetParam(PostParams.Mood).ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Wanna\"");
                contents.AppendLine();
                contents.AppendLine(bp.GetParam(PostParams.Wanna).ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Music\"");
                contents.AppendLine();
                contents.AppendLine(bp.GetParam(PostParams.Music).ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Access\"");
                contents.AppendLine();
                contents.AppendLine(GetCloseLevel(bp.Type));
//
                DateTime posttime = String.IsNullOrEmpty(bp.GetParam(PostParams.Date).ToString())?
                    DateTime.Now : (DateTime)bp.GetParam(PostParams.Date);
                ///////////
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Day\"");
                contents.AppendLine();
                contents.AppendLine(posttime.Day.ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Month\"");
                contents.AppendLine();
                contents.AppendLine(posttime.Month.ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Year\"");
                contents.AppendLine();
                contents.AppendLine(posttime.Year.ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Hour\"");
                contents.AppendLine();
                contents.AppendLine(posttime.Hour.ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"Minute\"");
                contents.AppendLine();
                contents.AppendLine(posttime.Minute.ToString());
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"NoComments\"");
                contents.AppendLine();
                contents.AppendLine("3");
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"show_comment\"");
                contents.AppendLine();
                contents.AppendLine("0");
                //
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"GroupID\"");
                contents.AppendLine();
                contents.AppendLine("0");
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"CanVote\"");
                contents.AppendLine();
                contents.AppendLine("default");
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"CanViewResults\"");
                contents.AppendLine();
                contents.AppendLine("default");
                //
                if (!String.IsNullOrEmpty(bp.SpecialParam))
                {
                    contents.AppendLine(header);
                    contents.AppendLine("Content-Disposition: form-data; name=\"DefaultJournal\"");
                    contents.AppendLine();
                    contents.AppendLine(bp.SpecialParam);
                }
//
                contents.AppendLine(header);
                contents.AppendLine("Content-Disposition: form-data; name=\"add\"");
                contents.AppendLine();
                contents.AppendLine("1");
                // Footer
                contents.AppendLine(footer);

                // This is sent to the Post
                byte[] bytes = Encoding.GetBytes(contents.ToString());
                myHttpWebRequest.ContentLength = bytes.Length;
                using (Stream requestStream = myHttpWebRequest.GetRequestStream())
                {
                    requestStream.Write(bytes, 0, bytes.Length);
                    requestStream.Flush();
                    requestStream.Close();
                }
                myHttpWebRequest.AllowAutoRedirect = false;
                myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                //получаем ответ
#if DEBUG
                reply = (new StreamReader(myHttpWebResponse.GetResponseStream(), this.Encoding)).ReadToEnd();
#endif
                myHttpWebResponse.Close();

                //////////////////////////
                ///////////end///////////
                /// POSTDATA =-----------------------------114782935826962
                /*
Content-Disposition: form-data; name="mna"

912198
-----------------------------114782935826962
Content-Disposition: form-data; name="mnb"

4222910360
-----------------------------114782935826962
Content-Disposition: form-data; name="post"


-----------------------------114782935826962
Content-Disposition: form-data; name="postid"


-----------------------------114782935826962
Content-Disposition: form-data; name="back"


-----------------------------114782935826962
Content-Disposition: form-data; name="hidden_by_admin"


-----------------------------114782935826962
Content-Disposition: form-data; name="text"


-----------------------------114782935826962
Content-Disposition: form-data; name="test"

ÒÅÑÒ
-----------------------------114782935826962
Content-Disposition: form-data; name="plainmode"

0
-----------------------------114782935826962
Content-Disposition: form-data; name="HTMLMessage"

1
-----------------------------114782935826962
Content-Disposition: form-data; name="ProKey"

1
-----------------------------114782935826962
Content-Disposition: form-data; name="user"

e_chichvarkin@mail.ru
-----------------------------114782935826962
Content-Disposition: form-data; name="DefaultJournal"

143447619
-----------------------------114782935826962
Content-Disposition: form-data; name="Subject"

Çàãîëîâîê
-----------------------------114782935826962
Content-Disposition: form-data; name="Body"

òåêñò åó÷åò
-----------------------------114782935826962
Content-Disposition: form-data; name="orfo"

Ðóññêèé ÿçûê
-----------------------------114782935826962
Content-Disposition: form-data; name="Tags"

òýã
-----------------------------114782935826962
Content-Disposition: form-data; name="MoodText"


-----------------------------114782935826962
Content-Disposition: form-data; name="MoodID"

0
-----------------------------114782935826962
Content-Disposition: form-data; name="Wanna"


-----------------------------114782935826962
Content-Disposition: form-data; name="Music"


-----------------------------114782935826962
Content-Disposition: form-data; name="Day"

20
-----------------------------114782935826962
Content-Disposition: form-data; name="Month"

2
-----------------------------114782935826962
Content-Disposition: form-data; name="Year"

2010
-----------------------------114782935826962
Content-Disposition: form-data; name="Hour"

22
-----------------------------114782935826962
Content-Disposition: form-data; name="Minute"

42
-----------------------------114782935826962
Content-Disposition: form-data; name="Access"

public
-----------------------------114782935826962
Content-Disposition: form-data; name="GroupID"

0
-----------------------------114782935826962
Content-Disposition: form-data; name="NoComments"

3
-----------------------------114782935826962
Content-Disposition: form-data; name="show_comment"

0
-----------------------------114782935826962
Content-Disposition: form-data; name="CanVote"

default
-----------------------------114782935826962
Content-Disposition: form-data; name="CanViewResults"

default
-----------------------------114782935826962
Content-Disposition: form-data; name="add"

1
-----------------------------114782935826962--
*/
                ////////////////////////
                ps.Error = null;
                if (myHttpWebResponse.StatusCode == HttpStatusCode.Found)
                {
                    ps.sLink = new Uri(myHttpWebResponse.Headers[HttpResponseHeader.Location]);

                    bp.Existance = true;
                }
                else
                {
                    bp.Existance = false;
                }
            }
            catch (Exception we)
            {
                Log("MakePost WebError: " + we.Message);
                ps.Error = we;
            }
            //
            return ps;
        }

        /// <summary>
        /// Разные параметры в зависимости от уровня доcтупа
        /// </summary>
        /// <param name="pt"></param>
        static string GetCloseLevel(PostType pt)
        {
            switch (pt)
            {
                case PostType.Private:
                    return "private";
                case PostType.FriendsOnly:
                    return "friends";
                default:
                //case PostType.Public:
                    return "public";
            }

        }

        /// <summary>
        /// Выкладывание записи в блоге
        /// </summary>
        /// <param name="user">Аккаунт блогера</param>
        /// <param name="cp">коммент для блога</param>
        /// <returns></returns>
        public override PostResult MakeComment(UserAccount user, CommentPost cp)
        {
            var ps = new PostResult {Error = new NotImplementedException()};
            try
            {
                if (!ValidateLink(cp.Link.OriginalString))
                {
                    throw new Exception("Cant comment on " + cp.Link.OriginalString);
                }
                //определим путь по которому обращаться для постинга.
                //logging
                if (!LogInto(user))
                {
                    throw new Exception("BlogsMail: не удалось залогинится");
                }
                //access_select 
                HttpWebRequest myHttpWebRequest = MakeRequest(cp.Link.OriginalString);
                //вначале нужен гет, чтобы получить секретные числа(!)

                myHttpWebRequest.AllowAutoRedirect = false;
                var myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                //получаем ответ

                string reply = (new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding)).ReadToEnd();

                Match m = new Regex(@"<input[^>]+?name\W+mna[^>]+?value\W+(\d+)[^>]+>").Match(reply);
                if (!m.Success) throw new Exception("Cant fing MNA secret number");
                string mna = m.Groups[1].Value;
                m = new Regex(@"<input[^>]+?name\W+mnb[^>]+?value\W+(\d+)[^>]+>").Match(reply);
                if (!m.Success) throw new Exception("Cant fing MNB secret number");
                string mnb = m.Groups[1].Value;
                /////////////////////////
                myHttpWebRequest = MakeRequest(cp.Link.OriginalString+
                                                              (String.IsNullOrEmpty(cp.Link.Query)?"?thread=0&page=1&skip=0#comment_0":""));
                myHttpWebRequest.Method = "POST"; // метод POST
                myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
                myHttpWebRequest.Referer = "http://blogs.mail.ru";
                // ставим False, чтобы при получении кода 302 не делать автоматический редирект
                myHttpWebRequest.AllowAutoRedirect = false;

                //Domain=mail.ru&Login=$u&Password=$p&page=&post=&login_from=
                // передаем параметры
                string sQueryString = String.Format("Poster={0}&Subject={1}&Comment={2}&replyto=0&back=/&addcomment=&mna={3}&mnb={4}",
                    user.username,cp.Subject,cp.Body,mna,mnb);
                //странности с кодировкой =(
                byte[] byteArr = Encoding.GetBytes(sQueryString);
                myHttpWebRequest.ContentLength = byteArr.Length;
                myHttpWebRequest.GetRequestStream().Write(byteArr, 0, byteArr.Length);
                // выполняем запрос
                myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
#if DEBUG
                string rets = new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding).ReadToEnd();
#endif
                myHttpWebResponse.Close();
                if (myHttpWebResponse.StatusCode == HttpStatusCode.Found)
                {

                    Match getthread = rComments.Match(myHttpWebResponse.Headers[HttpResponseHeader.Location]);
                    if(!getthread.Success)
                    {
                        ps.Error = new NotSupportedException("Cant find comment after posting it");
                        cp.Existance = false;
                    }else
                    {
                        ps.sLink = new Uri(string.Format("http://{0}{1}?thread={2}", cp.Link.Host, cp.Link.AbsolutePath, getthread.Groups[1]));
                        cp.Existance = true;
                        ps.Error = null;
                    }
                }
            }
            catch (Exception we)
            {
                Log("MakeComment WebError: " + we.Message);
                ps.Error = we;
            }
            //
            return ps;
        }

        /// <summary>
        /// Залогинивание на server
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public override bool LogInto(UserAccount user)
        {
            if (_isLoggedIn) return true;
            ///////////залогинивание уже с кукой
            HttpWebRequest myHttpWebRequest = MakeRequest("http://win.mail.ru/cgi-bin/auth");
            myHttpWebRequest.Method = "POST"; // метод POST
            myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
            myHttpWebRequest.Referer = "http://mail.ru";
            // ставим False, чтобы при получении кода 302 не делать автоматический редирект
            myHttpWebRequest.AllowAutoRedirect = false;

            //Domain=mail.ru&Login=$u&Password=$p&page=&post=&login_from=
            // передаем параметры
            string sQueryString = "Domain=mail.ru"+
                "&Login=" + user.username + "&Password=" + user.password;
            byte[] byteArr = _encoding.GetBytes(sQueryString);
            myHttpWebRequest.ContentLength = byteArr.Length;
            myHttpWebRequest.GetRequestStream().Write(byteArr, 0, byteArr.Length);
            // выполняем запрос
            HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
            //string rets = new StreamReader(myHttpWebResponse.GetResponseStream(),Encoding.GetEncoding(1251)).ReadToEnd();
            //получили куку
            sCookie = CookieParse(myHttpWebResponse.Headers[HttpResponseHeader.SetCookie]);
            myHttpWebResponse.Close();
            //переходим туда куда послали
            if (String.IsNullOrEmpty(myHttpWebResponse.Headers[HttpResponseHeader.Location]))
            {
                throw new Exception("blogs.mail.ru: Login attempt failed, no redirection.");
            }
            myHttpWebRequest = MakeRequest(myHttpWebResponse.Headers[HttpResponseHeader.Location]);
            myHttpWebRequest.AllowAutoRedirect = false;
            // выполняем запрос
            myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
            if (String.IsNullOrEmpty(myHttpWebResponse.Headers[HttpResponseHeader.Location]))
            {
                //возможна ситуация, когда ящик блокируется за неиспользование...
                //URL=http://win.mail.ru/cgi-bin/enableuser?login=e_chichvarkin&domain=mail.ru
                if (myHttpWebRequest.Address.OriginalString.Contains("&fail=1&ad=1"))
                {
                    //получили куку
                    sCookie = CookieParse(myHttpWebResponse.Headers[HttpResponseHeader.SetCookie]);
                    myHttpWebResponse.Close();
                    myHttpWebRequest = MakeRequest(String.Format("http://win.mail.ru/cgi-bin/enableuser?login={0}&domain=mail.ru", user.username));
                    myHttpWebRequest.AllowAutoRedirect = false;
                    // выполняем запрос
                    myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                    myHttpWebResponse.Close();
                    //аккаунт был заблокирован, поэтому мы провалимся до след. раза...
                    throw new Exception("blogs.mail.ru: Login attempt failed, accaunt needs reactivation.");
                }
                //раньше это считалось ошибкой, теперь нет.
                //throw new Exception("blogs.mail.ru: Login attempt failed, no redirection.");
            }
            else//нудно запросить еще одну страницу
            {
                myHttpWebRequest = MakeRequest(myHttpWebResponse.Headers[HttpResponseHeader.Location]);
                myHttpWebRequest.AllowAutoRedirect = false;
                // выполняем запрос
                myHttpWebResponse = (HttpWebResponse) myHttpWebRequest.GetResponse();
                //this._sCookie += "; "+this.CookieParse(myHttpWebResponse.Headers[HttpResponseHeader.SetCookie]);
                //string rets = new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding.GetEncoding(1251)).ReadToEnd();
                myHttpWebResponse.Close();
            }

            _isLoggedIn = sCookie.Contains("Mpop=");
            Log("LogInto " + user + " gains cookie = " + sCookie);
            ///
            if (_isLoggedIn) LoggedInAs = user;
            return _isLoggedIn;
        }

        #endregion

        #region ILike

        public Dictionary<string, int> GetLikes(Uri Link)
        {
            var oRet = new Dictionary<string, int>();
            try
            {
                System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();

                var result = client.GetStringAsync(String.Format(
                "https://connect.mail.ru/share_count?callback=1&func=a&url_list={0}",
                HttpUtility.UrlEncode(Link.OriginalString))).Result;

                MatchCollection mc = Regex.Matches(result, @"(shares|clicks)""\D+(\d+)\D",RegexOptions.IgnoreCase|RegexOptions.Singleline);
                foreach (Match match in mc)
                {
                    oRet.Add(match.Groups[1].Value, int.Parse(match.Groups[2].Value));
                }
            }
            catch (Exception e1)
            {
                Debug.WriteLine(e1);
            }
            return oRet;
        }

        #endregion

        #region IVideoHost

        /// <summary>
        /// просто ссылки на видео
        /// </summary>
        /// <example>http://my.mail.ru/video/mail/raisova1992/_myvideo/1.html#video=/mail/raisova1992/_myvideo/1</example>
        public static readonly string sVideo = "my.mail.ru/video";

        /// <summary>
        /// http://my.mail.ru/video/mail/raisova1992/_myvideo/1.html?ajax=photoitem&ajax_call=1&func_name=&mna=&mnb=&encoding=windows-1251
        /// </summary>
        public static readonly string sAjaxFormat =
            "http://{0}{1}.html?ajax=photoitem&ajax_call=1&func_name=&mna=&mnb=&encoding=windows-1251";

        /// <summary>
        /// http://content.video.mail.ru/inbox/kistin/19005/i-19097.jpg
        /// </summary>
        private static readonly string sImageFormat = "http://content.video.mail.ru{0}.jpg";
        
        /// <summary>
        /// добавлено 03.10.2010
        /// </summary>
        private static readonly Regex rDate = new Regex(@"добавлено\s+([\d\.]+)", Regexoptions);

        /// <summary>
        /// data-comments-count=\"165\"
        /// </summary>
        //private static readonly Regex rCommentsCount = new Regex(@"data\-comments?\-(?:count|show)[^\d>]+(\d+)\D", Regexoptions);

        /// <summary>
        /// class="b-catalog__video-item-rating font-small icon-mmw_video_icon_eye">9 745</span>
        /// </summary>
        private static readonly Regex rViewsCount = new Regex(@"<span[^>]+class\W+[^""]+video_icon_eye[^>]+>([\d ]+)<", Regexoptions);

        /// <summary>
        /// \"videoTitle\" : \"КЫЗ УЗАТУ РОЗА\"
        /// </summary>
        private static readonly Regex rVideoTitle = new Regex(@"<title>([^<]+?)(?:\s–)", Regexoptions);

        /// <summary>
        ///  "name": "Роза Раисова",
        /// </summary>
        private static readonly Regex rUserName = new Regex(@"""name""[^""]+""([^""]+)\W", Regexoptions);

        /// <summary>
        /// Извлечение данных о видео
        /// </summary>
        /// <param name="link"></param>
        /// <returns></returns>
        public Tuple<VideoData, BlogPost> GetVideoData(Uri link)
        {
            //wrong
            ////http://my9.imgsmail.ru/r/video2/player_v2.swf?par=http://content.video.my.mail.ru/mail/waleriyzvonarj/_vblogs/$2998$0$0
            //if (link.Host.Contains("imgsmail.ru") && !String.IsNullOrEmpty(link.Query))
            //{
            //    Uri.TryCreate(HttpUtility.ParseQueryString(link.Query)["par"], UriKind.Absolute, out link);
            //}
            var oRet = new Tuple<VideoData, BlogPost>(
                new VideoData(link),
                new BlogPost(link) { Existance = false, Links = 0, Comments = 0 });
            try
            {
                string [] parts =
                    link.OriginalString.Split(new [] { sVideo, ".htm", "#video=" }, StringSplitOptions.None);

                if (link.OriginalString.Contains(sVideo))
                {
                    //mail/raisova1992/_myvideo/1
                    string sKeyValue = link.OriginalString.Contains("#video=")?parts.Last():parts[1];

                
                    Uri postlink;
                    if (Uri.TryCreate(String.Format(sAjaxFormat, sVideo, sKeyValue),
                                      UriKind.Absolute, out postlink))
                    {
                        var myHttpWebRequest = (HttpWebRequest)WebRequest.Create(postlink);
                        myHttpWebRequest.AllowAutoRedirect = true;
                        var myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                        if (myHttpWebResponse.StatusCode == HttpStatusCode.OK)
                        {
                            string reply = new StreamReader(myHttpWebResponse.GetResponseStream(), 
                                Encoding.UTF8).ReadToEnd();

                            string imageLink = String.Format(sImageFormat, sKeyValue);
                            imageLink = imageLink.Insert(imageLink.LastIndexOf('/')+1, "i-");
                            //"http://content.video.mail.ru/inbox/kistin/19005/i-19097.jpg";


                            //Match img = rThumbnail2.Match(reply);
                            //if (img.Success)
                            //{
                                oRet.Item1.Replace = "<a href=\"" +
                                          link.OriginalString + "\"><img src=\"" + imageLink +
                                          "\"/>[Видео]</a>";
                                oRet.Item1.Images += "<img src=\"" + imageLink + "\"/>";
                            //}
                            ////а теперь просмотры!
                            Match vs = rViewsCount.Match(reply);
                            if (vs.Success)
                            {
                                oRet.Item1.Views += int.Parse(vs.Groups[1].Value.Replace(" ",""));
                            }
                            //vs = rCommentsCount.Match(reply);
                            //if (vs.Success)
                            //{
                            //    oRet.Item2.Comments += int.Parse(vs.Groups[1].Value);
                            //}
                            var mc = rUserName.Matches(reply);
                            if (mc.Count>0)
                            {
                                oRet.Item2.Subject = mc[mc.Count-1].Groups[1].Value;
                            }
                            Match pDate = rDate.Match(reply);
                            if (!pDate.Success || !DateTime.TryParseExact(pDate.Groups[1].Value, "dd.MM.yyyy",
                                CultureInfo.CurrentCulture,
                                DateTimeStyles.AssumeUniversal, out oRet.Item1.Published))
                            {
                                oRet.Item1.Published = DateTime.Now.AddMonths(-1);//чтобы не вставить текущий день
                            }
                            ////формирование поста...
                            Match title = rVideoTitle.Match(reply);
                            if (title.Success)// && Common.IsRussian(title.Groups[1].Value))
                            {
                                try
                                {
                                    oRet.Item2.Subject += ": " + title.Groups[1].Value;
                                    oRet.Item2.Existance = true;
                                    oRet.Item2.Published = oRet.Item1.Published;
                                    oRet.Item2.Views = oRet.Item1.Views;
                                    oRet.Item2.Links = 0;
                                    //////////////
                                    oRet.Item1.Title = oRet.Item2.Subject;
                                    //////////////

                                    oRet.Item2.Attributes = new PostAttributeCollection
                                        {
                                            new PostAttribute(PostParams.MediaThumbnail,
                                                              imageLink)
                                        };
                                }
                                catch (Exception e1)
                                {
                                    Debug.WriteLine(e1.Message);
                                }
                            }

                        }
                        myHttpWebResponse.Close();
                    }
                }
            }
            catch (Exception e1)
            {
                Debug.Write(e1);
            }
            return oRet;
        }

        public string FormEmbedCode(Uri link, String adds = null)
        {
            throw new NotImplementedException();
        }

        #endregion

    }
}
